#region Summary

// 
// Owner : JackieHan 
// 
// Solution : LearnSolution
// 
// Project : JackieHan.DotNet.Expression
// 
// File : ExpressionTreeBase.cs
// 
// CopyRight : Copyright © 2010-2011 Skomart Corporation, All Rights Reserved 
// 
// Summary : EpressionTreee 基础
// 
// History : 
//			2010-10-22 10:12:39	    Create 
// 

#endregion

#region Using

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
using NUnit.Framework;

#endregion

namespace JackieHan.DotNet.LinQExpression
{
    /// <summary> 
    /// EpressionTreee 基础
    /// </summary>
    [TestFixture]
    public class ExpressionTreeBase
    {
        /// <summary>
        /// 拆分Expression表达式
        /// </summary>
        [Test]
        public void TestBase()
        {
            Expression<Func<int, bool>> exprTree = num => num > 5;

            ParameterExpression param = exprTree.Parameters[0]; //表达式参数（函数的参数）
            BinaryExpression operation = exprTree.Body as BinaryExpression;//函数体 number>5
            ParameterExpression left = operation.Left as ParameterExpression;//左边参数
            ConstantExpression right = operation.Right as ConstantExpression;//参数值

            string expressString = string.Format("Decomposed expression:{0}=>{1} {2} {3}", param.Name, left.Name, operation.NodeType,
                              right.Value);

            Console.WriteLine(expressString);

            Assert.AreEqual(expressString,"Decomposed expression:num=>num GreaterThan 5");
        }

        /// <summary>
        /// 创建lambda表达式num=>num>5
        /// </summary>
        [Test]
        public void CreateExpression()
        {
            ParameterExpression numParam = Expression.Parameter(typeof (int), "num");
            ConstantExpression five = Expression.Constant(5, typeof (int));
            BinaryExpression numGreaterThanFile = Expression.GreaterThan(numParam, five);
            Expression <Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(numGreaterThanFile,
                                                                                        new ParameterExpression[]
                                                                                            {numParam});
            Expression<Func<int, bool>> lambda2 = num => num > 5;
            Console.WriteLine(lambda2.ToString());
            Assert.AreEqual(lambda.ToString(), lambda2.ToString());
        }

        /// <summary>
        /// 执行表达式
        /// </summary>
        [Test]
        public void ExcuteExpression()
        {
            BinaryExpression be = Expression.Power(Expression.Constant(2D), Expression.Constant(3D));  //构建一个ExPression
            Expression<Func<double>> le = Expression.Lambda<Func<double>>(be);  //转化成lambda表达式
            Func<double> compiledExpression = le.Compile();//编译成可执行代理
            double result = compiledExpression();//执行

            Console.WriteLine(result);
            Assert.AreEqual(result, 8);
        }

        [Test]
        public void ModifyExpress()
        {
            Expression<Func<string, bool>> expr = name => name.Length > 10 && name.StartsWith("G");

            AndAlsoModifier modifier = new AndAlsoModifier();
            Expression modifiedExpression = modifier.ModifyToOrElse(expr);
            Console.WriteLine(expr.ToString());
            Console.WriteLine(modifiedExpression.ToString());
            Assert.AreNotEqual(expr.ToString(), modifiedExpression.ToString());
        }

        [Test]
        public void ExpressionAdd()
        {
            Expression<Func<string, bool>> expr1 = name => name.Length > 10;
            Expression<Func<string, bool>> expr2 = name => name.StartsWith("G");

            Expression<Func<string, bool>> expr1Expr2 = name => name.Length > 10 && name.StartsWith("G");

            var dynamicExpression = expr1.AndAlso(expr2);

            Console.WriteLine(expr1Expr2.ToString());
            Console.WriteLine(dynamicExpression.ToString());

            var lambdaExpression = Expression.AndAlso(expr1, expr2);
            Console.WriteLine(lambdaExpression);

            Assert.AreEqual(expr1Expr2.ToString(), dynamicExpression.ToString());
        }

    }
}